package com.dhh.sky.service;

import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import com.dhh.sky.R;
import com.dhh.sky.SDAApplication;
import com.dhh.sky.activity.OperationListActivity;
import com.dhh.sky.model.Operation;
import com.dhh.sky.util.CUtil;
import com.dhh.sky.util.Config;
import com.dhh.sky.util.Constant;
import com.dhh.sky.util.FileManager;
import com.dhh.sky.util.OperationManager;
import com.microsoft.live.LiveAuthClient;
import com.microsoft.live.LiveAuthException;
import com.microsoft.live.LiveAuthListener;
import com.microsoft.live.LiveConnectClient;
import com.microsoft.live.LiveConnectSession;
import com.microsoft.live.LiveDownloadOperation;
import com.microsoft.live.LiveDownloadOperationListener;
import com.microsoft.live.LiveOperationException;
import com.microsoft.live.LiveStatus;
import android.app.IntentService;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
import android.widget.RemoteViews;

public class DownloadOperationService extends IntentService {
	private Notification notification;
	private NotificationManager notificationManager;
	private OperationManager om;
	private FileManager fm;
	private LiveDownloadOperation operation;
	private Operation op;
	private SDAApplication app;
	
	public DownloadOperationService(){
		super(Constant.SERVICE_NAME_UPLOAD);
	}

	@Override
	protected void onHandleIntent(Intent intent) {
		om = new OperationManager(getBaseContext());
		fm = new FileManager(getBaseContext());
		app = (SDAApplication)this.getApplication();     

		if(!CUtil.isNetworkAvailable(this)){
			om.removeOperation(Operation.OP_DOWNLOAD);
			responseConnectError(this.getString(R.string.msg_error_network));
			return;
		}
		
		initNotification();
		if(app.isConnected()){
			download();
		}else{
			final LiveAuthClient authClient = new LiveAuthClient(this,Config.CLIENT_ID);
			authClient.initialize(Arrays.asList(Config.SCOPES), new LiveAuthListener(){
	            @Override
	            public void onAuthError(LiveAuthException exception, Object userState) {
	            	om.removeOperation(Operation.OP_DOWNLOAD);
	            	responseConnectError(DownloadOperationService.this.getString(R.string.msg_error_connect));
	            	notificationManager.cancel(Constant.NOTIFICATION_DOWNLOAD_ID);
	            }

	            @Override
	            public void onAuthComplete(LiveStatus status,LiveConnectSession session,Object userState){
	                if (status==LiveStatus.CONNECTED) {
	                	app.initConnection(authClient, session, new LiveConnectClient(session));
	                    download();
	                }else{
	                	om.removeOperation(Operation.OP_DOWNLOAD);
	                	responseConnectError(DownloadOperationService.this.getString(R.string.msg_error_connect));
	                }
	            }
	        });
		}
	}
	
	private void download(){
		try {
			if(next())
				doDownload(initFile(op.getMeta()),op.getPath());
		} catch (Exception e) {
			Log.e(Constant.TAG, e.getMessage(),e);
		}
	}
	
	private boolean next(){
		boolean flag = false;
		List<Operation> ops = om.getOperationReady(Operation.OP_DOWNLOAD);
		if(ops.size()>0){
			flag = true;
			op = ops.get(0);
		}
		return flag;
	}
	
	private boolean doDownload(final File file,final String path){
		boolean flag = true;
		try{
			updateNotification(0,fm.getFile(path).getName(),getString(R.string.notification_downloading));
			op.setStatus(String.valueOf(Operation.STATUS_PROCESS));
			om.update(op);
			
			operation = app.getConnectClient().downloadAsync(path+"/content", file, new LiveDownloadOperationListener(){
				int current = 0;
				@Override
				public void onDownloadCompleted(LiveDownloadOperation operation){						
					updateNotification(100,null,getString(R.string.notification_download_success));
					om.removeOperation(op.getPath(), Integer.valueOf(op.getAction()));
					sendProgress(op.getPath(),100,true);					
					download();					
				}

				@Override
				public void onDownloadFailed(LiveOperationException exception, LiveDownloadOperation operation) {	
					updateNotification(0,null,getString(R.string.notification_download_error));
					op.setStatus(String.valueOf(Operation.STATUS_ERROR));
					om.update(op);
					sendProgress(op.getPath(),0,false);
					response(false,getString(R.string.notification_download_error),op.getTarget());
					download();			
				}

				@Override
				public void onDownloadProgress(int totalBytes, int bytesRemaining, LiveDownloadOperation operation) {
					int completed = countProgress(totalBytes, bytesRemaining);
					if(completed>=current+5){
						current = completed;
						updateNotification(current,null,null);
						sendProgress(op.getPath(),current,true);
					}					
				}});
			app.setDownloadloadOperation(operation);
		}catch(Exception e){
			Log.e(Constant.TAG, e.getMessage(), e);
			sendProgress(op.getPath(),0,false);
		}
		return flag;
	}
	
	private void initNotification(){
		notificationManager = (NotificationManager) getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE);
		Intent intent = new Intent(this,OperationListActivity.class);
		PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);		
		
		NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
		builder.setSmallIcon(android.R.drawable.stat_sys_download);
		//TODO change the icon
		Bitmap largeIcon = BitmapFactory.decodeResource(getResources(),R.drawable.ic_notif_upload);
		builder.setLargeIcon(largeIcon);
		
		builder.setContentIntent(pendingIntent);
		builder.setContent(new RemoteViews(getApplicationContext().getPackageName(), R.layout.download_progress));
		notification = builder.getNotification();
		notification.icon = android.R.drawable.stat_sys_download;
		notification.flags |= Notification.FLAG_AUTO_CANCEL;				
		
		notification.contentView.setProgressBar(R.id.status_progress, 100, 0, false);
	}
	
	private void updateNotification(int progress,String statusTitle,String statusMessage){
		if(statusTitle!=null)
			notification.contentView.setTextViewText(R.id.status_text, statusTitle);
		if(statusMessage!=null)
			notification.contentView.setTextViewText(R.id.status_message, statusMessage);
		notification.contentView.setProgressBar(R.id.status_progress, 100, progress, false);
		notificationManager.notify(Constant.NOTIFICATION_DOWNLOAD_ID, notification);
	}
	
	private File initFile(String fileName) throws IOException{
		File dir = new File(Constant.SKYDRIVE_LOCAL_PATH);
		if(!dir.exists()) 
			dir.mkdir();										
		File file = new File(Constant.SKYDRIVE_LOCAL_PATH+"/"+fileName);
		if(file.exists()){
			file.delete();
		}
		file.createNewFile();
		
		return file;
	}
	
	private int countProgress(long totalBytes, long bytesRemaining) {
        return (int) (((float)(totalBytes - bytesRemaining)) / totalBytes * 100);
    }
	
	private void sendProgress(String path, int progress,boolean isDone){
		Intent respone = new Intent(Constant.BOARDFAST_UPLOAD_PROGRESS);
		respone.putExtra(Constant.PARAM_PATH, path);
		respone.putExtra(Constant.PARAM_PROGRESS, progress);
		respone.putExtra(Constant.PARAM_DONE, isDone);
		sendBroadcast(respone);
	}
	
	protected void response(boolean isDone, String message, String path) {
		Intent respone = new Intent(Constant.SERVICE_NAME_BASIC);
		respone.putExtra(Constant.SERVICE_PARAM_ID, path);
		respone.putExtra(Constant.SERVICE_PARAM_DONE, isDone);
		respone.putExtra(Constant.SERVICE_PARAM_MSG, message);
		sendBroadcast(respone);
		Log.d(Constant.TAG, "response(): "+isDone);
	}
	
	private void responseConnectError(String msg){
		Intent respone = new Intent(Constant.SERVICE_NAME_CONNECT);
		respone.putExtra(Constant.SERVICE_PARAM_ERROR, true);
		respone.putExtra(Constant.SERVICE_PARAM_MSG, msg);
		sendBroadcast(respone);
	}
}
